﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using Microsoft.Win32;

namespace LTM_Extra
{
    public class ContentProvider
    {
        AuthorManager authorManager = null;
        TableOfContents toc = null;
        AppSetttings settings = null;

        public ContentProvider()
        {
#if DEBUG
            string filePath = AppDomain.CurrentDomain.BaseDirectory;
            //string filePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            
#else
            string filePath= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),Constants.ConfigurationFileFolder);
#endif

            authorManager = Util.CreateObjectByXml<AuthorManager>(Path.Combine(filePath, Constants.AuthorXmlFileName));
            
            settings = Util.CreateObjectByXml<AppSetttings>(Path.Combine(filePath, Constants.AppSettingsXmlFileName));

            if (TemplateFolderIsConfigured())
            {
                InitTOCObject();
            }

        }

        public bool TemplateFolderIsConfigured()
        {
            string tocXmlPath = Path.Combine(GetAppSettings(Constants.TemplateFolderKey), Constants.TOCXmlFileName);

          


            return File.Exists(tocXmlPath);
 
        }

        public void InitTOCObject()
        {
            string tocXmlPath = Path.Combine(GetAppSettings(Constants.TemplateFolderKey), Constants.TOCXmlFileName);

            if ( File.Exists(tocXmlPath))
            {
                toc = Util.CreateObjectByXml<TableOfContents>(tocXmlPath);
            }
        }

        public string GetAppSettings(string key)
        {
            var settingsDictionary = settings.Properties.ToDictionary<AppSetttingsProperties, string, string>(property => property.name, property => property.value);
            return settingsDictionary[key];

        }

        public void SetDefaultAuthor(string defaultAuthor)
        {
            settings.Properties.First(property => property.name == Constants.DefaultAuthorKey).value = defaultAuthor;
        }

        public void SetTemplateFolderPath(string templatePath)
        {
            settings.Properties.First(property => property.name == Constants.TemplateFolderKey).value = templatePath;
        }

        public bool TemplatePathChanged(string newTemplatePath)
        {
            return GetAppSettings(Constants.TemplateFolderKey) != newTemplatePath;
        }

        public IList<string> GetAuthorList()
        {
            return authorManager.Authors.Where(author => author != null).Select(author => author.Id).ToList();

        }

        public IList<string> GetWordTemplateCategories()
        {
            return toc.Word.Categories.Select(category => category.name).ToList();
        }

        public IDictionary<string, string> GetAuthorProperties(string authorId)
        {

            return authorManager.Authors.First(author =>author!=null&& author.Id == authorId)
                .Properties.ToDictionary<AuthorManagerAuthorsProperties, string, string>(property => property.name, property => property.value);

        }


       

        public void DeleteAuthor(string authorId)
        {
            for (int i = 0; i < authorManager.Authors.Length; i++)
            {
                if (authorManager.Authors[i]!=null&&authorManager.Authors[i].Id == authorId)
                {
                    authorManager.Authors[i] = null;
                }
            }

        }

        public void AddAuthor(IDictionary<string, string> properties)
        {
            AuthorManagerAuthors foundAuthor = authorManager.Authors.FirstOrDefault(author =>author!=null&& author.Id == properties[Constants.IdKey]);

            if (foundAuthor != default(AuthorManagerAuthors))
            {
                UpdateAuthor(properties[Constants.IdKey], properties);
                return;
            }

            AuthorManagerAuthors newAuthor = new AuthorManagerAuthors();
            newAuthor.Id = properties[Constants.IdKey];

            var result = (from property in properties select new AuthorManagerAuthorsProperties { name = property.Key, value = property.Value }).ToArray();

            newAuthor.Properties = result;

            authorManager.Authors = authorManager.Authors.Concat(new List<AuthorManagerAuthors> { newAuthor }).ToArray();

        }

        public void UpdateAuthor(string authorId, IDictionary<string, string> properties)
        {
            if (string.IsNullOrEmpty(authorId))
            {
                return;
            }
            AuthorManagerAuthors foundAuthor = authorManager.Authors.FirstOrDefault(author => author!=null&&author.Id == authorId);
            if (foundAuthor == null)
            {
                return;
            }

            foreach (var item in properties)
            {
                foundAuthor.Properties.First(property => property.name == item.Key).value = item.Value;


            }


        }

        public IList<Variable> GetAuthorVariables()
        {
            return authorManager.Variables.Select(variable => new Variable
            {
                VariableName = variable.name,
                LableText = variable.labelText,
                VariableType = variable.variableType,
                ValidationRule = variable.validationRule,
                Required = variable.required,
                InitialValue = variable.initialValues,
                ErrorMessage = variable.errorMessage,
                DefaultValue = variable.defaultValue
            }).ToList();
        }




        public IEnumerable<TableOfContentsWordCategoriesTemplates> GetWordTemplatesByCategory(string categoryName)
        {
            var result = from category in toc.Word.Categories where category.name == categoryName select category.Templates;
            if (result.Count() > 0)
            {
                return result.First();
            }
            throw new ArgumentException("Can't find templates by " + categoryName);
        }

        public IList<string> GetVariableNamesFromSelectedTemplate(string templateCategory, string templateName)
        {
            var template = GetSelectedTemplate(templateCategory, templateName);
            if (template.Variables == null)
            {
                return new List<string>();
            }
            return template.Variables.Where(variable=>variable!=null).Select(variable => variable.name).ToList();
        }


        public TableOfContentsWordCategoriesTemplates GetSelectedTemplate(string templateCategory, string templateName)
        {
            return toc.Word.Categories.Where(category => category.name == templateCategory).Select(category => category.Templates)
                              .First().Where(property => property.fileName == templateName).First();
        }



        public TableOfContentsWordCategoriesTemplatesVariables GetVariablePropertiesFormSelectedTemplate(string templateCategory, string templateName, string variableName)
        {
            var template = GetSelectedTemplate(templateCategory, templateName);
            if (template.Variables == null)
            {
                return null;
            }
            return template.Variables.Where(variable => variable != null && variable.name == variableName).First();

        }


        public void DeleteTemplateVariable(string templateCategory, string templateName, string variableName)
        {
            var template = GetSelectedTemplate(templateCategory, templateName);
            for (int i = 0; i < template.Variables.Length; i++)
			{
                if (template.Variables[i]!=null&&template.Variables[i].name == variableName)
                {
                    template.Variables[i] = null;
                }
			} 
        }

        public void UpdateTemplateVariable(string templateCategory, string templateName, Variable variable )
        {
            var variableProperties = GetVariablePropertiesFormSelectedTemplate(templateCategory, templateName, variable.VariableName);
            variableProperties.variableType = variable.VariableType;
            variableProperties.validationRule = variable.ValidationRule;
            variableProperties.required = variable.Required;
            variableProperties.labelText = variable.LableText;
            variableProperties.initialValues = variable.InitialValue;
            variableProperties.errorMessage = variable.ErrorMessage;
            variableProperties.defaultValue = variable.DefaultValue;
 
        }

        public void AddTemplateVariable(TableOfContentsWordCategoriesTemplates template, Variable variable)
        {
            if (template.Variables == null)
            {
                template.Variables = new TableOfContentsWordCategoriesTemplatesVariables[] { };
            }

            template.Variables = template.Variables.Concat(new List<TableOfContentsWordCategoriesTemplatesVariables>() 
          {new TableOfContentsWordCategoriesTemplatesVariables()
          { name=variable.VariableName,  labelText=variable.LableText, required=variable.Required,  variableType=variable.VariableType, errorMessage=variable.ErrorMessage, validationRule=variable.ValidationRule, initialValues=variable.InitialValue, defaultValue=variable.DefaultValue} 
          }).ToArray();

        }

        public IList<Variable> GetVariablesFormSelectedTemplate(string templateCategory, string templateName)
        {
            var template = GetSelectedTemplate(templateCategory, templateName);
            if (template.Variables == null)
            {
                return new List<Variable>();
            }
            return template.Variables.Select(
                propterty => new Variable() { VariableName = propterty.name,
                LableText = propterty.labelText, 
                VariableType = propterty.variableType,
                Required = propterty.required,
                InitialValue = propterty.initialValues,
                ValidationRule = propterty.validationRule,
                ErrorMessage = propterty.errorMessage,
                DefaultValue = propterty.defaultValue
                }).ToList();

        }

        public void SaveAppSetting()
        {
#if DEBUG
            string filePath=Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constants.AppSettingsXmlFileName);
           
#else
            string filePath=Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),Constants.ConfigurationFileFolder), Constants.AppSettingsXmlFileName);
#endif
           // MessageBox.Show(filePath);
            Util.SaveObjectTo<AppSetttings>(settings, filePath);

        }
        public void SaveAuthor()
        {
#if DEBUG
            string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constants.AuthorXmlFileName);

#else
            string filePath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Constants.ConfigurationFileFolder), Constants.AuthorXmlFileName);
#endif
            // MessageBox.Show(filePath);
            Util.SaveObjectTo<AuthorManager>(authorManager, filePath);
        }
        public void SaveTemplate()
        {

            if (!IsAdmin())
            {
                return;
            }

            string tocXmlPath = Path.Combine(GetAppSettings(Constants.TemplateFolderKey), Constants.TOCXmlFileName);
            //MessageBox.Show(tocXmlPath);
            if (File.Exists(tocXmlPath))
            {
                Util.SaveObjectTo<TableOfContents>(toc, tocXmlPath);
            }
        }

        public static bool IsAdmin()
        {
            return Registry.GetValue(Constants.RegistryPath, Constants.IsAdmin, "0").ToString()=="1";
        }


        //public  IDictionary<string,Style>  GetPredefinedStyleList()
        //{
        //    string styleXmlPath = Path.Combine(GetAppSettings(Constants.TemplateFolderKey), Constants.StylesXmlFileName);

        //    if (File.Exists(styleXmlPath))
        //    {
        //        return Util.CreateObjectByXml<Styles>(styleXmlPath).style.Select<StylesStyle, Style>(style => new Style() { Name = style.name, Discription = style.description, FriendlyName = style.friendlyName }).ToDictionary<Style, string>(style => style.Name);
        //    }
        //    return new Dictionary<string, Style>();
 
        //}


        

    }
}
